package com.itheima.reggie.filter;

import com.alibaba.fastjson.JSON;
import com.itheima.reggie.common.BaseContext;
import com.itheima.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

//Filter过滤器，用来过滤不是访问登录页面的请求过滤掉。

/**
 * filterName是这个过滤器的唯一命名，urlPatterns是过滤路径。
 * /*表示拦截所有请求的资源。
 * @Slf4j是lombok里的日志输出
 * @Configuration 没有这个配置类springboot加载不到filter
 */
@Slf4j
//@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
    //静态成员变量，可以只用初始化一次，所有成员方法共享。final修饰引用变量，其指向的地址不可以改变，但是其指向的内容可以改变。
    public static final AntPathMatcher antPathMatcher = new AntPathMatcher();
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //servletRequest是HttpServletRequest的父类，前者没有获取url的方法，所以要强转为子类HttpServletRequest；
        HttpServletRequest servletRequest1 = (HttpServletRequest) servletRequest;
        //返回除了host和ip等的部分
        String requestURI = servletRequest1.getRequestURI();
        log.info("放行前的URI"+requestURI);
       // log.info("拦截的路径；"+requestURI);
        //需要放行的请求，包括前端的所有静态页面，
        String[] url = {"/employee/login", "/employee/logout", "/backend/**", "/front/**"
        ,"/common/**","/user/sendMsg","/user/login"};
        //通过check判断，拦截的路径是否是合法的路径。
        if(check(url,requestURI)){
            //通过doFilter放行。
          //  log.info("本次请求不需要处理："+requestURI);
            filterChain.doFilter(servletRequest,servletResponse);
            /*
            这里为什么return之后，后面的语句还会执行，其实这是其中有一个请求过来，他是在init()加载后台页面时初始化然后getMemberList发送了一个
            /employee/page的请求过来，check判断为false，所以才会执行后面的代码。
             */
            return;
        }
       log.info("放行后的URI"+requestURI);
        //判断用户是否已经登录成功过，登录成功会在服务器留一个session对象，就是employee的id。
        Object lo=null;
        if((lo=servletRequest1.getSession().getAttribute("employee"))!=null){
            //登录成功之后，应该将session的id存入threadLocal中，供线程共享
            //而且是要在放行之前就把session的id存入threadLocal中，不然放行之后到了最后字段填充MyMetaObjectHandler时获取不到id值。
            BaseContext.setCurrentId((Long) lo);
           // log.info("denglu"+(Long)lo);  日志打印不能用,得用＋号连接
            filterChain.doFilter(servletRequest,servletResponse);
            return ;
        }
        if(servletRequest1.getSession().getAttribute("user")!=null){
            Long user = (Long)servletRequest1.getSession().getAttribute("user");
            BaseContext.setCurrentId(user);
            filterChain.doFilter(servletRequest,servletResponse);
            return ;
        }        //用户没有登录过
        HttpServletResponse servletResponse1 = (HttpServletResponse) servletResponse;
        //没有登陆过，就将错误信息封装为通用类R对象，然后通过toJSONString转换为JSON格式通过response传回给浏览器。
        //前端有一个request.js它里面有一个响应拦截器，可以拦截服务器发送回来的数据，要的格式就是R的通用格式。
        servletResponse1.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
      //  log.info("NOTLOGIN");
        return;
    }
    /**
     * 将拦截到的requestURI与需要放行的url请求进行match比较，符合就返回true。
     *
     * @return
     */
    public boolean check(String[] url,String requestURI) {
        /*
        AntPathMatcher的ant规则是？匹配一次且有且仅有一个。
        '/*'也是匹配一次，如/backend/*,可以是/backend/a,或者/backend/aa
        '/**'是匹配多次，可以匹配多级目录。
         */
        boolean bo=false;
        for (String s : url) {
            //用ant规则进行比较，
            bo=antPathMatcher.match(s,requestURI);
            if(bo){
                break;
            }
        }
        return bo;
    }
}
